#!/usr/bin/python
# encoding: utf-8

"""
@file: ineqs_funcs_v0.py
@time: 16/8/31 下午2:39
"""
from functools import reduce

from mathsolver.functions.base import *
from mathsolver.functions.budengshi import common_opers
from sympy import S, expand, fraction, simplify, cancel, factor, solveset
import re
from itertools import combinations


class Compare(BaseFunction):
    def solver(self, *args):
        f1 = args[0].sympify()
        f2 = args[1].sympify()
        f = expand(f1 - f2)
        self.steps.append(['令: f = (%s) - (%s)' % (new_latex(f1), new_latex(f2)), ''])
        symbs = f.free_symbols
        symons, const = common_opers.symoms_and_const(f)
        if len(symbs) == 1:  # 只含有一个未知变量
            symb = list(symbs)[0]
            coef = f.coeff(pow(symb, 2))
            top_point_f, top_point = common_opers.top_point_expr(f, symb)
            op_vaue = top_point[1]
            self.steps.append(['化简得 f = %s' % new_latex(top_point_f), ''])
            if coef > 0 and op_vaue >= 0:
                self.steps.append(['可以看出: f > 0', ''])
                result_ineq = BaseIneq([f1, '>=' if op_vaue == 0 else '>', f2])
            else:
                self.steps.append(['可以看出: f < 0', ''])
                result_ineq = BaseIneq([f1, '<=' if op_vaue == 0 else '<', f2])
            self.steps.append([r'\therefore ', result_ineq.printing()])
            self.output.append(result_ineq)
            return self
        else:  # 如果含有多个未知变量
            ineqs = args[2].sympify()
            symons_f = reduce(lambda a, b: a + b, symons)
            factor_f = factor(symons_f)
            mons, coef = list(factor_f.as_coefficients_dict().items())[0]
            self.steps.append(['化简得 f = %s' % new_latex(factor_f + const), ''])
            self.steps.append([r'\because %s, %s' % (ineqs[0].printing(), ineqs[1].printing())])
            if coef > 0:
                result_ineq = BaseIneq([f1, '>', f2])
            else:
                result_ineq = BaseIneq([f1, '<', f2])
            self.steps.append([r'\therefore ', result_ineq.printing()])
            self.output.append(result_ineq)
            self.label.add('比较大小-做差法')
            return self


# for step in Compare(verbose=True).solver(
#         BasePoly('a**5 + b**5 '), BasePoly('a**3*b**2 + a**2*b**3'),
#         BaseIneqs([['a', '>', '0'], ['b', '>', '0']])).steps:
#     print step[0], step[1]

# for step in Compare(verbose=True).solver(BasePoly('x-2'), BasePoly('x*x - x')).steps:
#     print step[0], step[1]

# for step in Compare(verbose=True).solver('x**2 + 4*b**2', '2*b').steps:
#     print step[0], step[1]


# for step in Compare(verbose=True).solver(sympify('m**2 + 1'), '0').steps:
#     print step[0], step[1]


# 2.求代数式的范围(OK)
# 输入方式一: 连接不等式。 如 1<a<2<b<3;       1<a<b<5;     a<b<5;     5<a<3<b
# 输入方式二: 分段不等式。 如 1<a<2; 2<b<3  1<a<b, a<b<5;  a<b, b<5;   5<a<3, 3<b
# 但是我们都要化简成方式二
# 任何目标表达式可以化为 s = f(x)/g(x) f(x)为任何表达式, g(x)为任何非零的表达式 s 就可以表示为f(x)的区间 和 1/g(x)区间的相乘。
# 而f(x)与g(x)求区间的方法是一样的, 所以我们只要定义一个通用的f(x)的求法即可,即转变为求已知变量的取值范围求函数定义值域的问题
class AlgebraScope(BaseFunction):
    # 前向或者后向搜索值
    @staticmethod
    def _find_real(ineq_expr_list, start, step_direction=1):
        ineq_ops = ['>', '<', '>=', '<=']
        end = len(ineq_expr_list) if step_direction > 0 else -1
        for i in range(start, end, step_direction):
            s = ineq_expr_list[i]
            if s not in ineq_ops and sympify(s).is_real:
                return s
        return None

    @staticmethod
    def to_ineq_expr_list(ineq_expr):
        ineq_expr_list = []  # 用列表结构,表示不等式[1, <, a, <, 2, <, b, <, 3]。
        tmp_ineq_e = ineq_expr
        ineq_ops = ['>', '<', '>=', '<=']
        while tmp_ineq_e:
            ineq_op_index = filter(lambda i: i > 0, map(lambda ineq_op: tmp_ineq_e.find(ineq_op), ineq_ops))
            ineq_op_index = list(ineq_op_index)
            if len(ineq_op_index) == 0:
                ineq_expr_list.append(tmp_ineq_e)
                break
            ineq_op_index = ineq_op_index[0]
            ineq_expr_list.append(tmp_ineq_e[0: ineq_op_index])
            ineq_op_step = 1 if tmp_ineq_e[ineq_op_index + 1] == '=' else 0
            ineq_expr_list.append(tmp_ineq_e[ineq_op_index: ineq_op_index + ineq_op_step + 1])
            tmp_ineq_e = tmp_ineq_e[ineq_op_index + ineq_op_step + 1:]
        return ineq_expr_list

    @staticmethod
    def ineq_symbol_interval(ineq, symb, ineq_expr_list=None):
        ineq_expr_list = ineq_expr_list if not ineq_expr_list else AlgebraScope.to_ineq_expr_list(ineq)
        s_index = [i for i, s_str in enumerate(ineq_expr_list) if s_str.find(str(symb)) >= 0][0]
        min_value = AlgebraScope._find_real(ineq_expr_list, s_index, -1)
        min_value = -S.Infinity if not min_value else min_value
        min_open = True if min_value == -S.Infinity or ineq_expr_list[s_index - 1] == '<' else False
        max_value = AlgebraScope._find_real(ineq_expr_list, s_index)
        max_value = S.Infinity if not max_value else max_value
        max_open = True if max_value == S.Infinity or ineq_expr_list[s_index + 1] == '<' else False
        return [(sympify(min_value), min_open), (sympify(max_value), max_open)]

    @staticmethod
    def analy_hide_ineq(ineq_str):
        p = r'([A-Za-z])(<=|<)([A-Za-z])'
        m = re.search(p, ineq_str)
        left_symb, ineq_op, right_symb = m.groups()
        return BaseIneq([left_symb, ineq_op, right_symb])

    @staticmethod
    def _symbol_interval(symbols_dict, e):
        for k, v in symbols_dict.items():
            if e.find(str(k)) >= 0:
                return v
        return None

    @staticmethod
    def _interval(interval_tuple):
        return Interval(interval_tuple[0][0], interval_tuple[1][0], left_open=interval_tuple[0][1],
                        right_open=interval_tuple[1][1])

    @staticmethod
    def _simple_expr_interval(e, symboles_interval_dict):
        e = expand(sympify(e))
        if e.is_Symbol:
            return AlgebraScope._interval(
                AlgebraScope._symbol_interval(symboles_interval_dict, str(e)))
        e_symbs = e.args
        intervals = map(lambda e_s: AlgebraScope._interval(
            AlgebraScope._symbol_interval(symboles_interval_dict, str(e_s))),
                        e_symbs)
        return reduce(common_opers.two_interval_add, intervals) if e.is_Add else reduce(common_opers.two_interval_mul,
                                                                                        intervals)

    def solver(self, *args):
        ineq_ops = ['>', '<', '>=', '<=']
        # {'a':[(min_value, min_open), (max_value, max_open)], 'b':[(min_value, min_open), (max_value, max_open)]}
        symbols_interval_dict = {}
        sym_p = r'([A-Za-z])'
        # symbs = re.findall(sym_p, str(args[-1].sympify()))
        # symbs = common_opers.ineqs_symbs(args[0].value)
        symbs = common_opers.ineqs_symbs(['-2', '<', 'x', '<', 'y', '3'])
        target_f_print = args[-1].printing()
        target_f = args[-1].sympify()
        tmp_symbs = symbs[::]
        # ineqs_list = args[0].value
        # ineq_str_list = list(map(lambda l: ''.join(l), ineqs_list))
        ineq_str_list = ['-2<x<y<3']
        for ineq_str in ineq_str_list:  # args[0:-1]
            cur_symbs = re.findall(sym_p, ineq_str)
            ineq_expr_list = AlgebraScope.to_ineq_expr_list(ineq_str)
            if len(cur_symbs) >= 2:  # 连串不等式 形如 1<a<b<3
                tmp_sys = filter(lambda ineq_sy: (ineq_sy not in ineq_ops) and isinstance(sympify(ineq_sy), Symbol), ineq_expr_list)  # 找出有那些符号变量
                tmp_sys = list(tmp_sys)
                for ineq_s in tmp_sys:
                    sym_intl = AlgebraScope.ineq_symbol_interval(ineq_str, ineq_s, ineq_expr_list)
                    symbols_interval_dict[ineq_s] = Interval(sym_intl[0][0], sym_intl[1][0], left_open=sym_intl[0][1], right_open=sym_intl[1][1])
            else:  # 单一不等式 如 1<a<3
                sym_intl = AlgebraScope.ineq_symbol_interval(ineq_str, cur_symbs[0], ineq_expr_list)
                symbols_interval_dict[cur_symbs[0]] = Interval(sym_intl[0][0], sym_intl[1][0], left_open=sym_intl[0][1], right_open=sym_intl[1][1])
            hide_intls = common_opers.analy_hide_ineq(ineq_str)  # 隐藏关系
            if hide_intls:
                for intl in hide_intls:
                    left_e, ineq_op, right_value = intl.sympify()
                    t = common_opers.unique_symbs(tmp_symbs, 1)[0]
                    tmp_symbs.append(str(t))
                    target_f = target_f.subs(left_e, t)
                    intl1 = solveset(str(t) + ineq_op + str(right_value), domain=S.Reals)
                    intl2 = common_opers.func_domain(left_e, symbols_interval_dict)
                    symbols_interval_dict[str(t)] = intl1.intersect(intl2)

        # ----------------------------New  End------------------------------------------
        self.steps.append(['由题意可知:', ''])
        for k, v in symbols_interval_dict.items():
            if k in symbs:
                self.steps.append(['%s的取值范围为:' % k, new_latex(v)])

        target_f_domain = common_opers.func_domain(target_f, symbols_interval_dict)
        self.steps.append(['%s的取值范围为:' % target_f_print, new_latex(target_f_domain)])
        self.output.append(BaseSymbolValue({'f': target_f_domain}))
        self.label.add('求代数式的范围')
        return self


# stepsolver = AlgebraScope(verbose=True).solver('12<a<60', '10<b<20', BaseExpression('b/a'))


# for step in AlgebraScope(verbose=True).solver('-1<=a<2', '-2<b<=1', 'a*b').steps:
#     print step[0], step[1]

# for step in AlgebraScope(verbose=True).solver('-pi/2<a<b<pi/2', BasePoly('a/b')).steps:
#     print step[0], step[1]


# for step in AlgebraScope(verbose=True).solver('-1<a<2', '-2<b<1', BasePoly('a-Abs(b)')).steps:
#     print step[0], step[1]


# for step in AlgebraScope(verbose=True).solver('12<a<b<36', BasePoly('a/b')).steps:
#     print step[0], step[1]

# for step in AlgebraScope(verbose=True).solver('1<a<2<b<3', BasePoly('a/b')).steps:
#     print step[0], step[1]


# for step in AlgebraScope(verbose=True).solver('-2<a<2<b<3', '-2<c<0', BasePoly('c*(a-b)')).steps:
#     print step[0], step[1]


# 3.分段不等式(OK)
# solveset(x**2 + 4*x > -5, x, domain=S.Reals).intersect(Interval(0, S.Infinity))
# solveset(4*x - x**2 > -5, x, domain=S.Reals).intersect(Interval(-S.Infinity, 0, right_open=True))
class FragmentIneqs(BaseFunction):
    def solver(self, *args):
        self.label.add('分段不等式')
        fs = args[0]  # 分段函数
        exprs = fs.expression
        if isinstance(exprs, Add) or len(exprs) == 1:
            raise 'try fail'
        expr_list = []
        for seg in exprs:
            seg_ineq = ''.join(seg['inequality'][0])
            seg_f = str(seg['main'])
            expr_list.append([seg_f, seg_ineq])
        target_e = args[-1]  # 目标不等式
        if isinstance(target_e, BaseExpression):
            expr_s = target_e.value
            p = '>=|>|<=|<'
            m = re.search(p, expr_s)
            ineq_op = m.group()
            ineq_info = expr_s.split(ineq_op)
            ineq_info.insert(1, ineq_op)
            target_e = BaseIneq(ineq_info)
        target_f, ineq_op, right = target_e.sympify()
        target_ineq_f = target_f - right
        x_symbol = list(target_ineq_f.free_symbols)[0]
        target_e_str = str(target_f) + str(ineq_op) + str(right)
        target_e_list = common_opers.to_ineq_expr_list(target_e_str)
        intervals = []
        # for f in args[0:-1]:
        for f in expr_list:
            x_interval_list = common_opers.to_ineq_expr_list(f[1])
            if len(x_interval_list) == 5:
                x_interval1 = solveset(sympify(x_interval_list[0] + x_interval_list[1] + x_interval_list[2]),
                                       domain=S.Reals)
                x_interval2 = solveset(sympify(x_interval_list[2] + x_interval_list[3] + x_interval_list[4]),
                                       domain=S.Reals)
                x_interval = x_interval1.intersect(x_interval2)
                self.steps.append(['当%s时' % f[1], '%s(x)=%s,' % (new_latex(target_f), new_latex(sympify(f[0])))])
            else:
                x_interval = solveset(sympify(f[1]), domain=S.Reals)
                self.steps.append(
                    ['当%s时' % new_latex(sympify(f[1])), '%s(x)=%s,' % (new_latex(target_f), new_latex(sympify(f[0])))])
            ineq_expr = f[0] + target_e_list[1] + target_e_list[2]
            f1_interval = solveset(sympify(ineq_expr), domain=S.Reals)
            seg_interval = x_interval.intersect(f1_interval)
            self.steps.append(['此时原不等式的的解集为:',
                               '空集' if not seg_interval else new_latex(seg_interval)])
            intervals.append(seg_interval)
        result = reduce(lambda interv1, interv2: interv1.union(interv2), intervals)
        self.steps.append(['综上,原不等式的解集为:', new_latex(result)])
        self.output.append(BaseSymbolValue({x_symbol: result}))
        return self


# 分段不等式
class FenDuanBuDengShi(BaseFunction):
    @staticmethod
    def seg_fxs_2_func(seg_fxs):
        func_value = {'name': 'f', 'type': ''}
        sym = list(sympify(seg_fxs[0][0]).free_symbols)[0]
        func_value['var'] = sym
        exprs = []
        for s, intl in seg_fxs:
            e = {'main': sympify(s), 'belong': ['', ], 'equality': ['', ]}
            e['inequality'] = common_opers.interval_2_ineq_list(intl, sym)
            exprs.append(e)
        func_value['expression'] = exprs
        return BaseFunc(func_value)

    def solver(self, *args):
        self.label.add('分段不等式')
        fs = args[0]  # 分段函数
        exprs = fs.expression
        if isinstance(exprs, Add) or len(exprs) == 1:
            raise 'try fail'
        expr_list = []
        for seg in exprs:
            seg_ineq = ''.join(seg['inequality'][0])
            seg_f = str(seg['main'])
            expr_list.append([seg_f, seg_ineq])
        target_e = args[-1]  # 目标不等式
        if isinstance(target_e, BaseExpression):
            expr_s = target_e.value
            p = '>=|>|<=|<'
            m = re.search(p, expr_s)
            ineq_op = m.group()
            ineq_info = expr_s.split(ineq_op)
            ineq_info.insert(1, ineq_op)
            target_e = BaseIneq(ineq_info)
        target_f, ineq_op, right = target_e.sympify()
        ineq_f = target_f - right
        x_symbol = list(ineq_f.free_symbols)[0]
        comp_fxs = common_opers.seg_comp_fxs(expr_list, ineq_f)
        comp_func = FenDuanBuDengShi.seg_fxs_2_func(comp_fxs)
        self.steps.append(['原不等式移项的: ', new_latex(ineq_f) + ineq_op + " 0"])
        self.steps.append(['\because ', fs.printing()])
        self.steps.append(['\therefore ', comp_func.printing()])
        r_intls = []
        for f, s_intl in comp_fxs:
            s_i = solveset(str(f) + ineq_op + '0', domain=S.Reals)
            r_i = s_i.intersect(s_intl)
            r_intls.append(r_i)
        last_intl = common_opers.intervals_union(r_intls)
        self.steps.append(['解得不等式的解集为: ', new_latex(last_intl)])
        # target_symb = list(sympify(comp_fxs[0][0]).free_symbols)[0]
        # intl_value = common_opers.to_base_interval(last_intl)
        self.output.append(BaseSymbolValue({x_symbol: last_intl}))
        return self


# print BaseExpression('f(x)>1').value

# func = {'var': 'x', 'expression': [
#     {'main': 'x**2 + 4*x', 'equality': [], 'belong': [], 'inequality': [['x', '>=', '0']]},
#     {'main': '4*x - x**2', 'equality': [], 'belong': [], 'inequality': [['x', '<', '0']]}], 'type': '',
#         'name': 'f'}
# #
# basef = BaseFunc(func)
# BaseSymbolValue

# for step in FragmentIneqs(verbose=True).solver(basef,
#                                                BaseIneq(['f(x)', '>', '-5'])).steps:
#     print step[0], step[1]


# for step in FragmentIneqs(verbose=True).solver(['x**2 + 4*x', 'x>=0'], ['4*x - x**2', 'x<0'],
#                                                BaseIneq(['f(x)', '>', '-5'])).steps:
#     print step[0], step[1]


# for step in FragmentIneqs(verbose=True).solver(['(x+1)**2', 'x<=-1'], ['2*(x+1)', '-1<x<1'], ['1/x - 1', 'x>=1'],
#                                                BaseIneq(['f', '>', '1'])).steps:
#     print step[0], step[1]


# for step in FragmentIneqs(verbose=True).solver(['x + 2', 'x<=0'], ['-x + 2', 'x>0'],
#                                                BaseIneq(['f', '<=', 'x**2'])).steps:
#     print step[0], step[1]


# 4.解绝对值不等式(OK)
class AbsIneq(BaseFunction):
    def solver(self, *args):
        self.label.add('解绝对值不等式')
        left, op, right = args[0].sympify()
        f = left - right
        x_symbol = list(f.free_symbols)[0]
        # f = args[0]
        f_segments = common_opers.segment_absed_expr(f)

        # target_ineq = args[1]
        # target_ineq = args[0]
        # target_f, ineq_op, right = target_ineq.sympify()

        def interval_2_str(interv):
            if interv.left == -S.Infinity:
                return 'x%s' % ('<' if interv.right_open else '<=') + str(interv.right)
            elif interv.right == S.Infinity:
                return 'x%s' % ('>' if interv.left_open else '>=') + str(interv.left)
            else:
                return str(interv.left) + '%sx%s' % (
                    '<' if interv.left_open else '<=', '<' if interv.right_open else '<=') + str(interv.right)

        # fi_args = map(lambda f_s: [str(f_s[0]), interval_2_str(f_s[1])], f_segments)
        # fi_args.append(target_ineq)
        # result = FragmentIneqs(verbose=True).solver(*fi_args).output[0]
        # self.output.append(result)
        result_intls = []
        # -----------------输出---------------
        for p, intv in f_segments:
            self.steps.append(['当x属于%s时:f(x)=%s' % (new_latex(intv), new_latex(p)), ''])
            seg_ineq = '%s %s %s' % (str(p), op, '0')
            self.steps.append(['不等式可化为:' + seg_ineq, ''])
            seg_intval = solveset(seg_ineq, domain=S.Reals).intersect(intv)
            result_intls.append(seg_intval)
            self.steps.append(['解的x取值范围为:' + new_latex(seg_intval), ';'])
        result = common_opers.intervals_union(result_intls)
        self.steps.append(['综述原函数的解集为:', new_latex(result)])
        # self.output.append(common_opers.to_base_interval(result))
        self.output.append(BaseSymbolValue({x_symbol: result}))
        return self


# for step in AbsIneq(verbose=True).solver(BaseIneq(['Abs(2*log(x, 1/2) - 3)', '>', '1'])).steps:
#     print step[0], step[1]


# for step in AbsIneq(verbose=True).solver('|2*x + 1|-|x-4| + |3*x + 2|', BaseIneq(['f', '>', '2'])).steps:
#     print step[0], step[1]


# for step in AbsIneq(verbose=True).solver('|x - 5| - |2*x + 3|', 'f(x)<1').steps:
#     print step[0], step[1]

# for step in AbsIneq(verbose=True).solver(BaseIneq(['Abs(x- 1) + Abs(x - 2)', '<=', '2'])).steps:
#     print step[0], step[1]


# 5.含绝对值的函数求最值
class AbsFunctionOptimum(BaseFunction):
    def solver(self, *args):
        f = args[0]
        txt = args[1]
        optimum = 'max' if txt.find('最大') >= 0 else 'min'  # 是最大值还是最小值
        opt_func = max if optimum == 'max' else min
        abs_items = re.findall('\|(.*?)\|', f)  # 提取绝对值项目
        abs_item_ineqs = map(lambda abs_item: (abs_item + '<=0', abs_item + '>=0'), abs_items)
        abs_item_faltten_ineqs = common_opers.flatten(abs_item_ineqs)
        combin_ineqs = combinations(abs_item_faltten_ineqs, len(abs_items))

        def dup_pair_ineqs(ineqs):
            return filter(lambda two_ineqs:
                          common_opers.to_ineq_expr_list(two_ineqs[0])[0] ==
                          common_opers.to_ineq_expr_list(two_ineqs[1])[0],
                          combinations(ineqs, 2))

        combin_ineqs = filter(lambda ineqs: len(dup_pair_ineqs(ineqs)) == 0, combin_ineqs)
        intervals = filter(lambda intv: not isinstance(intv, EmptySet), map(common_opers.solve_ineqs, combin_ineqs))
        seg_values = []
        f_list = map(lambda intv: (common_opers.simply_absed_expr(f, intv), intv), intervals)
        for f_e, intvl in f_list:
            self.steps.append(['当%s时 ' % common_opers.print_interval(intvl), 'f(x)=%s ;' % new_latex(f_e)])
            left_value = intvl.left
            seg_values.append(
                (f_e, intvl, common_opers.eval_expr(f_e, left_value) if left_value.is_real else left_value))
            right_value = intvl.right if intvl.right.is_real else None
            seg_values.append(
                (f_e, intvl, common_opers.eval_expr(f_e, right_value) if right_value.is_real else right_value))
        op_value = opt_func(seg_values, key=lambda seg: seg[2])
        self.steps.append(['综述:', '原函数的%s值为:%s' % ('最大' if optimum == 'max' else '最小', op_value[2])])
        # print op_value
        self.label.add('含绝对值的函数求最值')
        return self


# for step in AbsFunctionOptimum(verbose=True).solver('|2*x + 1|-|x - 4|', '最小值').steps:
#     print step[0], step[1]


# 6.分式不等式求解(OK)
class JieBuDengShi003(BaseFunction):
    OPPO_INEQ_OPS = {'>': '<', '>=': '<=', '<': '>', '<=': '>='}

    def solver(self, *args):
        ineq = args[0]
        left, ineq_op, right = ineq.sympify()
        ineq_solveset = solveset(str(left) + ineq_op + str(right), domain=S.Reals)
        f = cancel(simplify(left - right))
        variable = list(f.free_symbols)[0]
        general_term = BaseIneq([f, ineq_op, 0])
        numerator, den = fraction(f)
        if den.is_real:
            raise Exception('not fraction ineq')
        new_term = factor(numerator * den)
        coeff = new_term.as_coefficients_dict().values()[0]
        new_term = new_term / coeff
        ineq_op = ineq_op if coeff > 0 else JieBuDengShi003.OPPO_INEQ_OPS[ineq_op.strip()]
        last_ineq = BaseIneq([new_term, ineq_op, 0])
        # print solveset(str(f) + ineq_op + '0', domain=S.Reals)
        # ------------输出------------------
        self.steps.append(['原函数:' + ineq.printing(), ',移项通分得:' + general_term.printing()])
        self.steps.append(['不等式等价于:', last_ineq.printing()])
        self.steps.append(['综述解为:', ineq_solveset])
        self.label.add('解分式不等式')
        # self.output.append(common_opers.to_base_interval(ineq_solveset))
        self.output.append(BaseSymbolValue({variable: ineq_solveset}))
        return self


# for step in InEqSolve(verbose=True).solver(BaseIneq(['x/(1-x)', '>', '2*x'])).steps:
#     print step[0], step[1]


# 7.连串不等式求解(OK)
class ChainInEq(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseIneqs):
            ineq_list = args[0].value
        else:
            ineq_chain = args[0]
            ineq_chain = common_opers.replace_abs_str(ineq_chain)
            ineq_list = common_opers.to_ineq_expr_list(ineq_chain)
        ineq_list = map(str, ineq_list)
        result_interval = common_opers.solve_ineqs(
            [ineq_list[0] + ineq_list[1] + ineq_list[2], ineq_list[2] + ineq_list[3] + ineq_list[4]])
        variable = list(sympify(ineq_list[2]).free_symbols)[0]
        # self.output.append(result_interval)
        # ------输出----------
        ineqs = BaseIneqs([[ineq_list[0], ineq_list[1], ineq_list[2]], [ineq_list[2], ineq_list[3], ineq_list[4]]])
        self.steps.append(['原不等式等价于:', ineqs.printing()])
        self.steps.append(['不等式1的解集为:', new_latex(solveset(ineq_list[0] + ineq_list[1] + ineq_list[2], domain=S.Reals))])
        self.steps.append(['不等式2的解集为:', new_latex(solveset(ineq_list[2] + ineq_list[3] + ineq_list[4], domain=S.Reals))])
        self.steps.append(['故原不等式的解集为:', new_latex(result_interval)])
        self.label.add('解不等式组')
        # self.output.append(common_opers.to_base_interval(result_interval))
        self.output.append(BaseSymbolValue({variable: result_interval}))
        return self


# for step in ChainInEq(verbose=True).solver('5 <= 2*x - 5< 9').steps:
#     print step[0], step[1]

# for step in ChainInEq(verbose=True).solver(BaseIneqs(['5', '<=', '2*x - 5', '<', '9'])).steps:
#     print step[0], step[1]


# 解不等式
# 25229859	{"main":"已知函数f(x)=|x-2|-|x-5|,则不等式f(x)≥x^{2}-8x+15的解集为.
# class JieBuDengShi004(BaseFunction):
#     def solver(self, *args):
#         func = args[0]
#         func_expr = func.value['expression']
#         x_symb = list(sympify(func_expr).free_symbols)[0]
#         ineq_expr = args[1].value
#         p = r'f\((.*?)\)'
#         ineq_expr_x_term = re.search(p, ineq_expr).groups()[0]
#         func_expr = sympify(func_expr)
#         new_func_expr = func_expr.subs(x_symb, ineq_expr_x_term)
#         f_x_term = re.findall(r'f\(.*?\)', ineq_expr)[0]
#         new_ineq_expr = ineq_expr.replace(f_x_term, str(new_func_expr))
#         ineqs_list = common_opers.to_ineq_expr_list(new_ineq_expr)
#         target_ineq = BaseIneq(ineqs_list)
#         self.steps.append(['目标不等式变换得: ', target_ineq.printing()])
#         ineq_solve_set = solveset(new_ineq_expr, domain=S.Reals)
#         self.steps.append(['解得不等式: ', latex(ineq_solve_set)])
#         self.label.add('解不等式')
#         return self
# 如果是元函数调用 则paramer1:BaseEq, paramer2:字符串 形如"f(x) > 2*x"
#
class JieBuDengShi004(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BasePoly):
            func_expr = args[0].sympify()
        elif isinstance(args[0], dict):
            func_expr = args[0]['expression']
        elif isinstance(args[0], BaseEq):
            func_expr = args[0].sympify()[1]
        else:
            func_expr = args[0].value['expression']
        if isinstance(args[1], str):
            ineq_expr = args[1]
            ineq_expr_str = ineq_expr
            last_ineq = ineq_expr
        else:
            ineq_expr = args[1].value
            ineq_expr_str = ''.join(ineq_expr)
            last_ineq = ineq_expr_str
        fxs = common_opers.search_fxs(ineq_expr_str)
        for fx in fxs:
            last_ineq = last_ineq.replace(fx, str(common_opers.comp_func(func_expr, fx)))
        ineqs_list = common_opers.to_ineq_expr_list(last_ineq)
        target_ineq = BaseIneq(ineqs_list)
        l, _, r = target_ineq.sympify()
        f = l - r
        variable = list(f.free_symbols)[0]
        self.steps.append(['目标不等式变换得: ', target_ineq.printing()])
        ineq_solve_set = solveset(last_ineq, domain=S.Reals)
        self.steps.append(['解得不等式: ', new_latex(ineq_solve_set)])
        self.label.add('解不等式')
        # self.output.append(common_opers.to_base_interval(ineq_solve_set))
        self.output.append(BaseSymbolValue({variable: ineq_solve_set}))
        return self


if __name__ == '__main__':
    # for step1, step2 in JieBuDengShi004(verbose=True).solver(BasePoly('Abs(x-2)-Abs(x-5)'),
    #                                                          BaseIneq(['f(x)', '>=', 'x**2 - 8*x + 15'])).steps:
    #     print step1, step2
    pass
